package com.electronic.utils.pdf;

import com.electronic.domain.PositionInfo;
import com.electronic.utils.ICommonUtil;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author: IFCA
 * @Description: pdf相关工具类
 */
@Slf4j
public class PDFTools {

    private static Logger logger = LoggerFactory.getLogger(PDFTools.class);


    /**
     * 判断当前传入的页码是否都存在，有一个不存在就返回false
     *
     * @param pdfReader  文件对象
     * @param pageNumber 页码字符串(9,6,12,8)
     */
    public static boolean isMultiplePageNumbersExist(PdfReader pdfReader, String pageNumber) {
        // 初始化返回值为true
        boolean isExist = true;
        try {
            // 使用PdfReader读取PDF文件
            int countPage = pdfReader.getNumberOfPages();
            // 检查pageNumber是否不为空且不为空白
            if (StringUtils.isBlank(pageNumber)) {
                return false;
            }

            // 如果pageNumber是单个数字
            if (StringUtils.isNumeric(pageNumber)) {
                // 将字符串转换为整数
                int page = Integer.parseInt(pageNumber);
                // 如果超出范围内返回false
                if (page < 0 || page > countPage) {
                    // 如果超出范围内返回false
                    return false;
                }
            } else {
                // 将逗号分隔的字符串拆分成数组
                String[] pageNumbers = pageNumber.split(",");
                for (String numStr : pageNumbers) {
                    // 检查每个部分是否为数字
                    if (StringUtils.isNumeric(numStr)) {
                        // 将字符串转换为整数
                        int page = Integer.parseInt(numStr);
                        // 如果页码无效（小于等于0或大于总页数），设置isExist为false并退出循环
                        if (page <= 0 || page > countPage) {
                            isExist = false;
                            break;
                        }
                    } else {
                        // 如果不是数字，设置isExist为false并退出循环
                        isExist = false;
                        break;
                    }
                }
            }
        } catch (Exception e) {
            logger.error("查找页码出错", e);
            // 如果发生IO异常，则认为未找到有效页码，并设置isExist为false
            isExist = false;
        }

        return isExist;
    }

    /**
     * 关键字判断
     *
     * @param pdfReader  文件对象
     * @param pageNumber 文件页码
     * @param keyWord    关键字
     */
    public static boolean isKeyWordExist(PdfReader pdfReader, String pageNumber, String keyWord) {
        boolean isExist = true;
        try {
            // 初始化PDF解析对象
            if (pdfReader != null) {
                // pdf解析监听器
                PdfRenderListener pdfListener = new PdfRenderListener();
                // pdf页码数
                int pages = pdfReader.getNumberOfPages();
                // 需要解析的关键字
                pdfListener.setKeyWord(keyWord);
                // 实例化pdf文本流处理器
                PdfReaderContentParser processor = new PdfReaderContentParser(pdfReader);
                // 组装页码
                int[] pageNumbers = getPageNumber(pageNumber, pages);
                List<PDFSignKeyWordCoordinate> list = new CopyOnWriteArrayList<PDFSignKeyWordCoordinate>();
                // 循环页数进行相关的设置并判断是否还有关键字
                for (int i = 0; i < pageNumbers.length; i++) {
                    processor.processContent(pageNumbers[i], pdfListener);
                    // 当解析到关键字坐标时，跳出文件解析过程
                    if (pdfListener.hasCompleted()) {
                        // 得到文本渲染对象，获取关键字坐标值
                        List<TextRenderInfo> textRenderInfoList = pdfListener.getTextRender();
                        for (int n = 0, k = textRenderInfoList.size(); n < k; n++) {
                            PDFSignKeyWordCoordinate pdfSignKeyWordCoordinate = new PDFSignKeyWordCoordinate();
                            pdfSignKeyWordCoordinate.setRenderInfo(textRenderInfoList.get(n));
                            pdfSignKeyWordCoordinate.setSignaturePage(i);
                            list.add(pdfSignKeyWordCoordinate);
                        }
                        pdfListener.setHasCompleted(false);
                        pdfListener.setTextRender(new CopyOnWriteArrayList<>());
                    }
                }
                // 查找到关键字直接返回成功
                if (list.size() > 0) {
                    return isExist;
                } else {
                    // 未找到关键字直接返回失败
                    return false;
                }
            } else {
                // 直接返回关键字查找失败
                return false;
            }
        } catch (IOException e) {
            logger.error("查找关键字出错", e);
            return false;
        }
    }

    /**
     * 将页码字符串解析为整数数组
     *
     * @param pageNumber 页码字符串(9,6,12,8)
     * @param countPage  PDF总页数
     * @return 页码数组
     */
    private static int[] getPageNumber(String pageNumber, int countPage) {
        // 初始化返回值为null
        int[] ints = null;
        // 如果pageNumber是单个数字
        if (StringUtils.isNumeric(pageNumber)) {
            // 将字符串转换为整数
            int page = Integer.parseInt(pageNumber);
            if (page == 0) {
                // 如果是0，返回从1到总页数的数组
                ints = new int[countPage];
                for (int i = 1; i <= countPage; i++) {
                    // 填充数组，从1到countPage
                    ints[i - 1] = i;
                }
            } else {
                // 返回包含该页码的数组
                ints = new int[1];
                ints[0] = page;
            }
        } else {
            // 将逗号分隔的字符串拆分成数组
            String[] pageNumbers = pageNumber.split(",");
            // 初始化结果数组
            ints = new int[pageNumbers.length];
            for (int i = 0; i < pageNumbers.length; i++) {
                // 去除每个部分的空白
                String numStr = pageNumbers[i].trim();

                if (StringUtils.isNumeric(numStr)) {
                    // 检查每个部分是否为数字并将其转换为整数
                    int page = Integer.parseInt(numStr);

                    if (page > 0 && page <= countPage) {
                        // 如果页码有效（大于0且小于等于总页数），添加到结果数组中
                        ints[i] = page;
                    }
                }
            }
        }
        // 返回包含该页码的数组
        return ints;
    }

    /**
     * 坐标签署坐标返回
     *
     * @param oriFile    pdf文件对象
     * @param pageNumber 页码
     * @param x          文件对应的左上角X坐标
     * @param y          文件对应的左上角Y坐标
     * @param width      宽度
     * @param height     高度
     */
    public static List<PositionInfo> coordinateReturnPositionInfo(String oriFile, String pageNumber, float x, float y, float width, float height) {
        // 创建坐标对象
        List<PositionInfo> positionInfoList = new CopyOnWriteArrayList<>();
        try {
            PdfReader pdfReader = new PdfReader(oriFile);
            // pdf页码数
            int pages = pdfReader.getNumberOfPages();
            //解析页码(例如1-5解析为1,2,3,4,5)
            String newPages = ICommonUtil.parsePages(pageNumber);
            // 组装页码
            int[] pageNumbers = getPageNumber(newPages, pages);
            // 循环页数进行相关的设置
            for (int number : pageNumbers) {
                PositionInfo crossPageSeal = new PositionInfo();
                // 设置宽度
                crossPageSeal.setImgWidth(width);
                // 设置高度
                crossPageSeal.setImgHeight(height);
                // 设置坐标X对象
                crossPageSeal.setPositionX(x);
                // 设置坐标Y对象
                crossPageSeal.setPositionY(y);
                // 设置页数
                crossPageSeal.setPageNo(number);
                positionInfoList.add(crossPageSeal);
            }
            return positionInfoList;
        } catch (Exception e) {
            logger.error("coordinateReturnPositionInfo：微调坐标异常", e);
        }
        return positionInfoList;
    }

    /**
     * 关键字签署坐标返回
     *
     * @param oriFile    pdf文件对象
     * @param pageNumber 页码
     * @param keyword    关键字
     * @param width      宽度
     * @param height     高度
     * @return
     */
    public static List<PositionInfo> keywordReturnPositionInfo(String oriFile, String pageNumber, String keyword, float width, float height) {
        // 创建坐标对象
        List<PositionInfo> crossPageSealList = new CopyOnWriteArrayList<>();
        try {
            // pdf解析监听器
            PdfRenderListener pdfListener = new PdfRenderListener();
            PdfReader pdfReader = new PdfReader(oriFile);
            // pdf页码数
            int pages = pdfReader.getNumberOfPages();
            // 需要解析的关键字
            pdfListener.setKeyWord(keyword);
            // 实例化pdf文本流处理器
            PdfReaderContentParser processor = new PdfReaderContentParser(pdfReader);
            //解析页码(例如1-5解析为1,2,3,4,5)
            String newPages = ICommonUtil.parsePages(pageNumber);
            // 组装页码
            int[] pageNumbers = getPageNumber(newPages, pages);

            List<PDFSignKeyWordCoordinate> list = new CopyOnWriteArrayList<PDFSignKeyWordCoordinate>();
            // 循环页数进行相关的设置并判断是否还有关键字
            for (int number : pageNumbers) {
                processor.processContent(number, pdfListener);
                // 当解析到关键字坐标时，跳出文件解析过程
                if (pdfListener.hasCompleted()) {
                    // 得到文本渲染对象，获取关键字坐标值
                    List<TextRenderInfo> textRenderInfoList = pdfListener.getTextRender();
                    for (TextRenderInfo textRenderInfo : textRenderInfoList) {
                        PDFSignKeyWordCoordinate pdfSignKeyWordCoordinate = new PDFSignKeyWordCoordinate();
                        pdfSignKeyWordCoordinate.setRenderInfo(textRenderInfo);
                        pdfSignKeyWordCoordinate.setSignaturePage(number);
                        list.add(pdfSignKeyWordCoordinate);
                    }
                    pdfListener.setHasCompleted(false);
                    pdfListener.setTextRender(new CopyOnWriteArrayList<>());
                }
            }
            // 如果 关键字坐标集合为空,说明未找到关键字或关键字坐标值
            return getPositionInfosForKeyword(width, height, crossPageSealList, list, pdfReader, keyword);
        } catch (IOException e) {
            logger.error("查找关键字出错", e);
        }
        return crossPageSealList;
    }

    /**
     * 获取关键字坐标
     *
     * @param width
     * @param height
     * @param list
     * @param pdfReader
     * @param keyword
     * @return
     */
    private static List<PositionInfo> getPositionInfosForKeyword(float width, float height, List<PositionInfo> positionInfoList, List<PDFSignKeyWordCoordinate> list, PdfReader pdfReader, String keyword) {
        if (list.isEmpty()) {
            return positionInfoList;
        }

        float llx;
        float lly;
        float urx;
        float ury;
        for (PDFSignKeyWordCoordinate pdfSignKeyWordCoordinate : list) {
            TextRenderInfo renderInfoSign = pdfSignKeyWordCoordinate.getRenderInfo();
            com.itextpdf.awt.geom.Rectangle2D.Float boundingRectange = renderInfoSign.getBaseline().getBoundingRectange();
            float sealWidth = (width > 150) ? 150 : width;
            float sealHeight = (height > 150) ? 150 : height;

            llx = boundingRectange.x - (sealWidth - boundingRectange.width) / 2;
            lly = boundingRectange.y - (sealHeight
                    - (renderInfoSign.getAscentLine().getStartPoint().get(1) - boundingRectange.y))
                    / 2;
            // 如果llx小于0盖章会超出PDF的范围，所以在此处判断一下，若小于０，把坐标定位为正值
            llx = llx < 0 ? new BigDecimal(String.valueOf(llx)).abs().floatValue() : llx;

            PositionInfo positionInfo = new PositionInfo();
            positionInfo.setImgWidth(width);
            positionInfo.setImgHeight(height);
            positionInfo.setPositionX(llx);
            positionInfo.setPositionY(lly);
            // 设置页数
            positionInfo.setPageNo(pdfSignKeyWordCoordinate.getSignaturePage());

            positionInfoList.add(positionInfo);
        }
        return positionInfoList;
    }
}
